﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Dapper.Moon
{
    internal class NewExpressionProvider
    {
        private ExpressionProvide _expression = null;

        public NewExpressionProvider(ExpressionProvide expression)
        {
            _expression = expression;
        }

        /// <summary>
        /// 解析 i=>new {a = 1}
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public string Resolve(Expression exp)
        {
            StringBuilder sbSelectFields = new StringBuilder();
            NewExpression ne = exp as NewExpression;
            if (ne.Members == null) return "";
            for (var i = 0; i < ne.Members.Count; i++)
            {
                //别名或属性名
                string name = ne.Members[i].Name;
                //判断是否是属性访问、方法调用
                if (ne.Arguments[i].NodeType == ExpressionType.MemberAccess)
                {
                    MemberExpression mex = ne.Arguments[i] as MemberExpression;
                    //当前属性所属类型
                    Type entityType = mex.Member.ReflectedType;
                    if (entityType.ToString() == "System.String")
                    {
                        string methodName = mex.Member.Name;
                        switch (methodName)
                        {
                            case "Length":
                                sbSelectFields.Append(_expression.SqlDialect.Length(_expression.Resolve(mex.Expression))).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            default:
                                throw new Exception("unsupported expression");
                        }
                        //跳出本次循环
                        continue;
                    }
                    if (entityType.ToString() == "System.DateTime")
                    {
                        string methodName = mex.Member.Name;
                        switch (methodName)
                        {
                            case "Now":
                                sbSelectFields.Append(_expression.SqlDialect.GetDate).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            case "Year":
                                sbSelectFields.Append(_expression.SqlDialect.Year(_expression.Resolve(mex.Expression))).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            case "Month":
                                sbSelectFields.Append(_expression.SqlDialect.Month(_expression.Resolve(mex.Expression))).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            case "Day":
                                sbSelectFields.Append(_expression.SqlDialect.Day(_expression.Resolve(mex.Expression))).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            case "Hour":
                                sbSelectFields.Append(_expression.SqlDialect.Hour(_expression.Resolve(mex.Expression))).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                                break;
                            default:
                                throw new Exception("unsupported expression");
                        }
                        //跳出本次循环
                        continue;
                    }
                    //属性访问      
                    string argumentString = ne.Arguments[i].ToString();
                    string[] arguments = argumentString.Split('.');
                    string colName = arguments[arguments.Length - 1];
                    if (_expression.IsPrefix)
                    {
                        if (_expression.IsSubquery && arguments.Length == 2)
                        {
                            //兼容子查询
                            arguments = new string[] { arguments[0], arguments[0], arguments[1] };
                        }
                        //i.t1.id = t1.id 、 i.t1 = t1.*
                        //前缀
                        string prefix = arguments[1];
                        switch (arguments.Length)
                        {
                            case 2:
                                sbSelectFields.Append(prefix + ".*,");
                                break;
                            case 3:
                                //定义别名的情况
                                if (name != colName && _expression.IsAlias)
                                {
                                    colName = _expression.GetColumnName(entityType, colName);
                                    sbSelectFields.Append(prefix).Append(".").Append(_expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName).Append(" ").Append(name).Append(",");
                                }
                                else
                                {
                                    colName = _expression.GetColumnName(entityType, colName);
                                    sbSelectFields.Append(prefix).Append(".").Append(_expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName).Append(",");
                                }
                                break;
                        }
                    }
                    else
                    {
                        //定义别名的情况
                        if (name != colName && _expression.IsAlias)
                        {
                            colName = _expression.GetColumnName(entityType, colName);
                            colName = _expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName;
                            sbSelectFields.Append(colName).Append(" ").Append(name).Append(",");
                        }
                        else
                        {
                            colName = _expression.GetColumnName(entityType, colName);
                            sbSelectFields.Append(_expression.IsQuote ? _expression.SqlDialect.SetSqlName(colName) : colName).Append(",");
                        }
                    }
                }
                else if (ne.Arguments[i].NodeType == ExpressionType.Call)
                {
                    //方法调用
                    string result = _expression.Resolve(ne.Arguments[i]);
                    sbSelectFields.Append(result).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                }
                else
                {
                    string result = _expression.Resolve(ne.Arguments[i]);
                    sbSelectFields.Append(result).Append(" ").Append(_expression.IsAlias ? name : "").Append(",");
                }
            }
            if (sbSelectFields.Length > 1)
            {
                sbSelectFields.Remove(sbSelectFields.Length - 1, 1);
            }
            return sbSelectFields.ToString();
        }
    }
}
